<template>
  <div class="base-table-form">
    <div class="actionbar flex-space-between" v-if="isActionbar">
      <div></div>
      <div v-if="isTotalShow">总共：{{ form.data.length || 0 }}条</div>
    </div>
    <BaseForm ref="formRef" :size="size" :model="form" :rules="rules" label-width="100px">
      <BaseTable
        v-if="formType === 'table'"
        ref="tableRef"
        :size="size"
        :loading="loading"
        :isSelection="isSelection"
        :indexNumber="indexNumber"
        :height="height"
        :data="form.data"
      >
        <el-table-column
          v-for="(item, i) in columns"
          show-overflow-tooltip
          :key="i"
          :prop="item.prop"
          :label="item.label"
          :width="item.width"
          :align="item.align"
          :fixed="item.fixed"
          :label-class-name="item.required ? 'is-required' : ''"
        >
          <template #default="{ row, column, $index }">
            <BaseFormItem
              v-if="row.__edit__ && item.isEdit !== false && !readonly"
              label-width="0px"
              label
              :col="2"
              :prop="`data.${$index}.${item.prop}`"
              :rules="getRules(item, { row, column, $index })"
            >
              <el-input
                v-model.trim="row[item.prop]"
                :data="item.data"
                :row="row"
                :column="column"
                :index="$index"
                v-bind="getAttrs(item.attrs, { row, column, $index })"
              ></el-input>
            </BaseFormItem>
            <span v-else>{{ formatter(row, column, $index, row[item.prop]) }}</span>
          </template>
        </el-table-column>
        <!-- 后续统一用这个 -->
        <slot name="column-append" />
        <slot />
        <el-table-column v-if="!readonly && isOperation" align="center" prop label="操作" width="80">
          <template #header>
            <el-button type="primary" @click="add" :icon="Plus"></el-button>
          </template>
          <template #default="{ row }">
            <el-button type="danger" text @click="del(row)">删除</el-button>
          </template>
        </el-table-column>
      </BaseTable>
    </BaseForm>
  </div>
</template>
<script setup>
import BaseTable from "./base-table";
import BaseForm from "./base-form";
import BaseFormItem from "./base-form-item";
import { computed, nextTick, ref } from "vue";
import { ElMessageBox, ElMessage } from "element-plus";
import { Plus } from '@element-plus/icons-vue'

const props = defineProps({
  formType: {
    type: String,
    default: "table"
  },
  valueExtend: {
    type: Object,
    default: () => ({})
  },
  // 表格绑定值
  value: {
    type: Array,
    default: () => []
  },
  size: {
    type: String,
    default: "small"
  },
  loading: Boolean,
  isSelection: {
    type: Boolean,
    default: true
  },
  indexNumber: Boolean,
  isActionbar: {
    type: Boolean,
    default: true
  },
  isTotalShow: {
    type: Boolean,
    default: true
  },
  height: [String, Number],
  // 是否可新增
  isOperation: {
    type: Boolean,
    default: true
  },
  // 表格数据
  data: {
    type: Array,
    default: () => []
  },
  columns: {
    type: Array,
    default: () => {
      return [];
    }
  },
  rules: {
    type: Object,
    default: () => ({})
  },
  readonly: Boolean,
  // 表格行前置新增钩子
  beforeAddData: {
    type: Function,
    default: data => {
      return data;
    }
  },
  // 删除数据之后钩子
  beforeRemoveRow: {
    type: Function,
    default: () => true
  },
  // 删除数据之后钩子
  afterRemoveRow: {
    type: Function,
    default: () => {}
  },
  // 格式化方法，优先匹配Label后缀
  formatter: {
    type: Function,
    default: (row, column, index, value) => {
      return (
        row[`${column.property}Label`] ||
        row[`${column.property}__LABEL`] ||
        value
      );
    }
  },
  // 外部的操作按钮直接做整合
  actions: {
    type: Array,
    default: () => []
  }
});

const emits = defineEmits(['input'])

const checked = ref([]);
const baseActions = ref([
  {
    label: "新增",
    value: "add",
    type: "primary",
    sort: 0,
    event: "add"
  },
  {
    label: "删除",
    value: "delete",
    type: "danger",
    sort: 20,
    event: "del"
  }
]);

const formRef = ref();
const tableRef = ref()

const form = computed({
  get() {
    return {
      data: props.value.map((v, i) => {
        v.__edit__ = v.__edit__ || true;
        v.__index__ = i;
        Object.assign(v, props.valueExtend);
        return v;
      })
    };
  },
  set(val) {
    emits("input", val.data);
  }
});
const fieldData = computed(() => {
  return props.columns.reduce((cache, column) => {
    if (column.prop) {
      cache[column.prop] = column.defaultValue || "";
    }
    return cache;
  }, {});
});

const validate = computed(() => {
  return formRef.value.validate;
});
const resetFields = computed(() => {
  return formRef.value.resetFields;
});
const clearValidate = computed(() => {
  return formRef.value.clearValidate;
});

// 删除
async function del(row, msg = "", callback = props.afterRemoveRow) {
  const _checked = row.event === "del" ? checked.value : [row];

  const valid = await props.beforeRemoveRow(_checked);
  if (!valid) return;
  if (row.event !== "del") {
    deleteData(_checked, callback);
    return;
  }
  if (_checked.length === 0) {
    ElMessage.warning("请勾选需要删除的数据");
    return;
  }

  ElMessageBox.confirm(
    msg ||
      `<span style="color: #db3b21; font-weight: bolder; background-color: #fbe5e1; border-radius: 3px; padding: 2px 6px;">${checked.length}</span>条数据将被删除，是否继续`,
    "提示",
    {
      dangerouslyUseHTMLString: true,
      confirmButtonText: "确定",
      cancelButtonText: "取消"
    }
  )
    .then(() => {
      deleteData(checked, callback);
    })
    .catch(() => {});
}
// 删除表格数据
function deleteData(checked, callback) {
  const indexs = checked.map(c => c.__index__);
  form.value.data = form.value.data.filter(d => !indexs.includes(d.__index__));
  emits("input", form.value.data);
  formRef.value.clearValidate();
  callback(checked, form.value.data);
}
// 新增表格数据
function add() {
  const obj = props.beforeAddData(
    Object.assign(
      {},
      fieldData.value,
      { __edit__: true, __index__: form.value.data.length },
      props.valueExtend
    )
  );
  form.value.data.push(obj);
  emits("input", form.value.data);
  nextTick(() => {
    if (!tableRef.value) return;
    console.log(tableRef.value, '----tableRef.value----')
    tableRef.value.$table.$refs.bodyWrapper.scrollTop = tableRef.value.$table.$refs.bodyWrapper.scrollHeight;
  });
}
// 通过维数据匹配label
function getLabel(item, row) {
  const value = row[item.prop];
  if (!item.data || !item.data.length) {
    return value;
  }
  const obj = item.data.find(i => i.value === value);
  if (obj) {
    return obj.label;
  }
  return value;
}
// 表格列校验规则获取
function getRules(item, { row, column, $index }) {
  const rules = [];
  if (item.required) {
    rules.push({
      required: true,
      message: `请${item.trigger === "change" ? "选择" : "输入"}${item.label}`,
      trigger: item.trigger || "blur"
    });
  }
  if (item.uniqueness) {
    rules.push({
      validator: validateValue.value,
      trigger: item.trigger || "blur"
    });
  }
  if (item.rules) {
    if (typeof item.rules === "function") {
      return item.rules(rules, this, { row, column, $index }); // 自定义函数操作
    }
    return rules.concat(item.rules);
  }
  return rules;
}

// 获取控件配置
function getAttrs(attrs, { row, column, $index }) {
  if (typeof attrs === "function") {
    return attrs(this, { row, column, $index }); // 自定义函数操作
  }
  return attrs;
}

// 唯一性校验286371
function validateValue(rule, value, callback) {
  const { field } = rule;
  const arr = field.split(".");
  const index = arr[1];
  if (value) {
    const isRepetition = form.value.data.find(
      (item, i) => i.toString() !== index && value === item[arr[2]]
    );
    if (isRepetition) {
      callback(new Error("输入值已存在请输重新输入"));
      return;
    }
  }
  callback();
}

defineExpose({
  validate,
  resetFields,
  clearValidate
})
</script>
<style lang="scss">
.base-table-form-action.base-table-form {
  .base-form {
    height: calc(100% - 50px);
  }
}
.base-table-form {
  height: 500px;
  overflow: hidden;
  .actionbar {
    align-items: center;
  }
  .base-form {
    width: 100%;
    height: 100%;
    .base-form-actionbar {
      display: none;
      border: none;
    }
    .base-form-content {
      overflow: hidden;
      height: 100%;
      .el-form {
        height: 100%;
        padding: 0;
        overflow: hidden;
        .el-form-item {
          margin-bottom: 0;
        }
        .el-form-item__error {
          left: 6px;
          bottom: 0px;
          top: auto;
          left: auto;
          background: #fff;
          padding: 0 2px;
        }
      }
      .cell.is-required:not(.is-no-asterisk):before {
        content: "*";
        color: #f56c6c;
        margin-right: 4px;
      }
    }
  }
}
</style>
